﻿using System;
using System.Configuration;

namespace MyCommon.Configuration
{
    /// <summary>
    /// 配置文件中Section下的Settings集合，通常为add标签项，请为项的类型装饰ConfigurationSettingsKeyAttribute属性
    /// </summary>
    /// <typeparam name="T">集合中项的类型</typeparam>
    public class ConfigurationSettingsCollection<T> : ConfigurationElementCollection where T : ConfigurationElement, new()
    {
        /// <summary>
        /// 通过索引获取或设置元素
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public T this[int index]
        {
            get { return BaseGet(index) as T; }
            set { BaseAdd(index, value); }
        }
        /// <summary>
        /// 通过键值获取元素
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public new T this[string key]
        {
            get { return BaseGet(key) as T; }
        }
        /// <summary>
        /// 增加新元素
        /// </summary>
        /// <param name="settings"></param>
        public void Add(T settings)
        {
            BaseAdd(settings);
        }

        /// <summary>
        /// 创建新元素
        /// </summary>
        /// <returns></returns>
        protected override ConfigurationElement CreateNewElement()
        {
            return new T();
        }
        /// <summary>
        /// 获取元素的Key值
        /// </summary>
        /// <param name="element">元素对象</param>
        /// <returns></returns>
        protected override object GetElementKey(ConfigurationElement element)
        {
            var attr = Attribute.GetCustomAttribute(element.GetType(), typeof(ConfigurationSettingsKeyAttribute)) as ConfigurationSettingsKeyAttribute;
            if (attr == null)
            {
                throw new InvalidOperationException("ConfigurationSettingsCollection<T>，T必须装饰ConfigurationSettingsKeyAttribute属性");
            }
            return element.GetType().GetProperty(attr.Key).GetValue(element, null);
        }
    }
    /// <summary>
    /// 应用于ConfigurationSettingsCollection_T中单个项的类型声明上，标识该类型中用于键的属性名
    /// </summary>
    [AttributeUsage(AttributeTargets.Class)]
    public class ConfigurationSettingsKeyAttribute : Attribute
    {
        /// <summary>
        /// 构造ConfigurationSettingsKeyAttribute
        /// </summary>
        /// <param name="key">被装饰元素作为Key的属性名</param>
        public ConfigurationSettingsKeyAttribute(string key)
        {
            Key = key;
        }
        /// <summary>
        /// 被装饰元素作为Key的属性名
        /// </summary>
        public string Key { get; private set; }
    }
}
